﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using MTBrainStorm.Framework;
using MTBrainStorm.Framework.Commands.Parameters;
using MTBrainStorm.Multitouch.Behaviors;
using MTBrainStorm.Views;
using Messenger = MTBrainStorm.Framework.Messaging.Messenger;

namespace MTBrainStorm.ViewModels
{
    public class MultiTouchElementViewModel : ObservableObject
    {
        #region Properties

        private MatrixTransform _renderTransform;
        private Point _position = new Point(0, 0);
        private double _rotation;
        private double _scaleX = 1;
        private double _scaleY = 1;

        public Point ManipulationOrigin { get; set; }

        public MatrixTransform RenderTransform
        {
            get
            {
                var matrix = new Matrix();
                matrix.Translate(Position.X, Position.Y);
                matrix.RotateAt(Rotation, Position.X, Position.Y);
                matrix.ScaleAt(ScaleX, ScaleY, Position.X, Position.Y);

                _renderTransform = new MatrixTransform(matrix);

                return _renderTransform;
            }
            set {
                _renderTransform = value;
                RaisePropertyChanged("RenderTransform");
            }
        }

        public Point Position
        {
            get { return _position; }
            set
            {
                _position = value;
                RaisePropertyChanged("Position");
                RaisePropertyChanged("RenderTransform");
            }
        }

        public double Rotation
        {
            get { return _rotation; }
            set
            {
                _rotation = value;
                RaisePropertyChanged("Rotation");
                RaisePropertyChanged("RenderTransform");
            }
        }

        public double ScaleX
        {
            get { return _scaleX; }
            set
            {
                _scaleX = value;
                RaisePropertyChanged("ScaleX");
                RaisePropertyChanged("RenderTransform");
                RaisePropertyChanged("ActualWidth");
            }
        }

        public double ScaleY
        {
            get { return _scaleY; }
            set
            {
                _scaleY = value;
                RaisePropertyChanged("ScaleY");
                RaisePropertyChanged("RenderTransform");
                RaisePropertyChanged("ActualHeight");
            }
        }

        private double _actualWidth;
        public double ActualWidth
        {
            get { return Width*ScaleX; }
            set { 
                _actualWidth = value;
                RaisePropertyChanged("ActualWidth");
                RaisePropertyChanged("ScaleX");
            }
        }

        private double _actualHeight;
        public double ActualHeight
        {
            get { return Height * ScaleY; }
            set
            {
                _actualWidth = value;
                RaisePropertyChanged("ScaleY");
                RaisePropertyChanged("ActualHeight");
            }
        }

        private double _width;
        public double Width
        {
            get { return _width; }
            set
            {
                _width = value;
                RaisePropertyChanged("Width");
                RaisePropertyChanged("ActualWidth");
            }
        }

        public double Height { get; set; }
        
        #endregion

        #region Constructors

        public MultiTouchElementViewModel()
        {
            Width = 220;
            Height = 220;

            Messenger.Default.Register(this, this, new Action<ManipulationArgs>(ApplyManipualtions));
        }
        
        #endregion

        #region Helpers

        private readonly TouchParameterConverter _touchParameterConverter = new TouchParameterConverter();
        public IParameterConverter TouchParamConverter
        {
            get { return _touchParameterConverter; }
        }
        
        private void ApplyManipualtions(ManipulationArgs args)
        {
            if (args.Source != this)
                return;

            Position = args.Position;
            Rotation = Rotation + args.Rotation;
            ScaleX = ScaleX * args.ScaleX;
            ScaleY = ScaleY * args.ScaleY;
            ManipulationOrigin = args.ManipulationOrigin;
            RaisePropertyChanged("RenderTransform");
        }
        
        #endregion
    }
}
